/*
    Radio Battletoads Player
    Copyright (C) 2011 Jorge Suarez de Lis <yo@jorgesuarezdelis.name>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.radiobattletoads.player;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.AlertDialog;
import android.app.Service;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration.Status;
import android.os.IBinder;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class PlayerService extends Service implements Runnable,OnPreparedListener,OnErrorListener,OnCompletionListener, OnClickListener, OnBufferingUpdateListener {
	private static final String TAG = "PlayerService";
	MediaPlayer mp;
	Boolean thread_iniciado = false;
	static int player_status = RadioBattletoadsActivity.PLAYER_STOPPED;
	Boolean connection_blocked = false;
	static Boolean waiting_for_answer = false;
	static public String track;
	static Boolean destroyed_by_clicking_stop;
	private static int dialog = 0;
	static protected PlayerService instancia = null;
	
	public void run() {
		if(this.connection_blocked==false){
			if(this.checkConnection()==true){
				/* Change button/text */
				PlayerService.player_status = RadioBattletoadsActivity.PLAYER_INITIAL_BUFFERING;
				PlayButton.updateButtonAndStatus();
		        /* Set media player */
				Log.d("player","Setting media player...");
		        track = downloadPlaylist();
		        if(track!=null){
			        Log.d("player","Track: "+track);
			        try {
						mp.setOnPreparedListener(this);
					    mp.setOnErrorListener(this);
					    mp.setOnCompletionListener(this);
					    mp.setOnBufferingUpdateListener(this);
					    mp.reset();
			            mp.setDataSource(track);
			            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
			            Log.d("player","Preparing...");
			            mp.prepareAsync();
				    } catch (IOException e) {
				    	this.player_status = RadioBattletoadsActivity.PLAYER_IOEXCEPTION;
				    	PlayButton.updateButtonAndStatus();
				        Log.d("player","Failed to start: IOException");
				        this.stopSelf();
				    } catch (IllegalStateException ie){
				    	this.player_status = RadioBattletoadsActivity.PLAYER_DROPPED;
				    	PlayButton.updateButtonAndStatus();
				    	Log.d("player","Failed to start: IllegalStateException");
				    	this.stopSelf();
				    }
		        }
		        else{
		        	this.player_status = RadioBattletoadsActivity.PLAYER_NOPLAYLIST;
			    	PlayButton.updateButtonAndStatus();
			        Log.d("player","Failed to start: IOException");
			        this.stopSelf();
		        }
			}
			else{
				this.player_status = RadioBattletoadsActivity.PLAYER_BLOCKED;
		    	PlayButton.updateButtonAndStatus();
				this.stopSelf();
			}
		}
		else{
			Log.d("player","Connection blocked or answered negative!");
			this.stopSelf();
		}
	}
	
	private String downloadPlaylist(){
    	HttpClient hc = new DefaultHttpClient();
    	HttpGet hg = new HttpGet("http://www.radiobattletoads.com/escucha.m3u");
    	try {
			HttpResponse hr = hc.execute(hg);
			InputStream is = hr.getEntity().getContent();
			
			final char[] buffer = new char[0x10000];
			StringBuilder out = new StringBuilder();
			Reader in = new InputStreamReader(is, "UTF-8");
			int read;
			do {
			  read = in.read(buffer, 0, buffer.length);
			  if (read>0) {
			    out.append(buffer, 0, read);
			  }
			} while (read>=0);
			
			String track = out.toString();
			track = track.substring(0,track.indexOf("\r\n"));

			Log.d("playlist","Playlist: "+out.toString());
			Log.d("playlist","Selected track: "+track);
			
			return track;
			
		} catch (IOException e) {
			return null;
		}
    }
	
	private Boolean checkConnection(){
		HttpClient hc = new DefaultHttpClient();
    	HttpGet hg = new HttpGet("http://live.radiobattletoads.com:443/server_version.xsl");
    	try {
			HttpResponse hr = hc.execute(hg);
			StatusLine response = hr.getStatusLine();
			if(response.getStatusCode()==200) return true;
			else return false;
		} catch (IOException e) {
			return false;
		}
	}

	public void onBufferingUpdate(MediaPlayer mp, int percent) {
		Log.d("player","Player is buffering...");
		this.player_status = RadioBattletoadsActivity.PLAYER_BUFFERING;
		PlayButton.updateButtonAndStatus();
	}
	
	public void onPrepared(MediaPlayer mp) {
		Log.d("player","Player is prepared");
		NotificationManager.removeAllNotifications(this.getApplicationContext());
		NotificationManager.putPlayingNotification(this.getApplicationContext());
        mp.start();
        Log.d("player","Player is started");
        this.player_status = RadioBattletoadsActivity.PLAYER_PLAYING;
		PlayButton.updateButtonAndStatus();
	}

	public boolean onError(MediaPlayer mp, int what, int extra) {
		Log.d("player","Player sent error: "+what);
		NotificationManager.removeAllNotifications(this.getApplicationContext());
		this.player_status = RadioBattletoadsActivity.PLAYER_DROPPED;
		PlayButton.updateButtonAndStatus();
		
		this.stopSelf();
		return false;
	}

	public void onCompletion(MediaPlayer mp) {
		Log.d("player","Player completed? Uhm...");
		NotificationManager.removeAllNotifications(this.getApplicationContext());
		this.player_status = RadioBattletoadsActivity.PLAYER_DROPPED;
		PlayButton.updateButtonAndStatus();
		this.stopSelf();
	}

    @Override
    public IBinder onBind(Intent arg0) {
          return null;
    }
    @Override
    public void onCreate() {
    	
    	  if(this.instancia!=null){
    		  Log.d("player","There's another service running. WHAT'S HAPPENING?!");
    		  return;
    	  }
    	
          super.onCreate();
          mp = new MediaPlayer();
    	  Log.d("player","Player created");
    	  this.instancia = this;

    	  /* Remove dropped notification if still present */
    	  destroyed_by_clicking_stop = false;
    	  NotificationManager.removeDroppedNotification(this.getApplicationContext());
    	  
          /* Show connection alerts */
          Builder builder;
          ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
          NetworkInfo info = cm.getActiveNetworkInfo();
          if (info == null){
        	/* Alerts related to no connection */
        	this.showDialog(PlayerService.DIALOG_NOCONNECTION);
          }
          else{
        	/* Alerts related to broadband connections */
  	        int netType = info.getType();
  	        int netSubtype = info.getSubtype();
  	        
  	        if(ConnectivityManager.TYPE_MOBILE==netType && RadioBattletoadsActivity.warn_mobile){
  	        	this.showDialog(PlayerService.DIALOG_NETWORKTYPE);
  	        }
          }
    }
    
    public static final int DIALOG_PREVIOUS = 0, DIALOG_NODIALOG = 0;
    public static final int DIALOG_NOCONNECTION = 1;
    public static final int DIALOG_NETWORKTYPE = 2;
    public static final int DIALOG_BLOCKED = 3;
    
    static public void showDialog(int newdialog){
    	
    	Builder builder;
    	
    	if(newdialog!=DIALOG_PREVIOUS) PlayerService.dialog = newdialog;
    	
    	switch(PlayerService.dialog){
    	case DIALOG_PREVIOUS:
    		PlayerService.waiting_for_answer = false;
    		// Do nothing
    		break;
    	case DIALOG_NOCONNECTION:
    		PlayerService.waiting_for_answer = true;
          	builder = new AlertDialog.Builder(RadioBattletoadsActivity.instantiatedActivity);
          	builder.setNeutralButton(android.R.string.ok, PlayerService.instancia);
          	builder.setTitle(R.string.warning_noconnection_title);
  	  	    builder.setMessage(R.string.warning_noconnection_body);
          	builder.show();
    		break;
    	case DIALOG_NETWORKTYPE:
    		ConnectivityManager cm = (ConnectivityManager) PlayerService.instancia.getSystemService(Context.CONNECTIVITY_SERVICE);
    		NetworkInfo info = cm.getActiveNetworkInfo();
    		int netType = info.getType();
  	        int netSubtype = info.getSubtype();
    		PlayerService.waiting_for_answer = true;
        	builder = new AlertDialog.Builder(RadioBattletoadsActivity.instantiatedActivity);
        	builder.setPositiveButton(android.R.string.yes, PlayerService.instancia);
          	builder.setNegativeButton(android.R.string.no, PlayerService.instancia);
        	switch(netSubtype){
        		case TelephonyManager.NETWORK_TYPE_GPRS:
        		case TelephonyManager.NETWORK_TYPE_EDGE:
        			builder.setTitle(R.string.warning_2g_title);
        	  	    builder.setMessage(R.string.warning_2g_body);
        		break;
        		case TelephonyManager.NETWORK_TYPE_UMTS:
        			builder.setTitle(R.string.warning_3g_title);
        	  	    builder.setMessage(R.string.warning_3g_body);
        		break;
        		case TelephonyManager.NETWORK_TYPE_HSPA:
        		case TelephonyManager.NETWORK_TYPE_HSDPA:
        		case TelephonyManager.NETWORK_TYPE_HSUPA:
        			builder.setTitle(R.string.warning_hsdpa_title);
        	  	    builder.setMessage(R.string.warning_hsdpa_body);
        		break;
        		default:
        			builder.setTitle(R.string.warning_default_title);
        	  	    builder.setMessage(R.string.warning_default_body);
        	}
        	builder.show();
    		break;
    	case DIALOG_BLOCKED:
    		PlayerService.waiting_for_answer = true;
    		builder = new AlertDialog.Builder(RadioBattletoadsActivity.instantiatedActivity);
    	  	builder.setNeutralButton(android.R.string.ok, PlayerService.instancia);
    	  	builder.setTitle(R.string.warning_blocked_title);
  	    	builder.setMessage(R.string.warning_blocked_body);
  	    	builder.show();
    		break;
    	}
    	
    }
   
    @Override
    public void onDestroy() {
    	  Log.d("player","Player destroyed");
    	  mp.stop();
    	  mp.release();
    	  NotificationManager.removePlayingNotification(this.getApplicationContext());
    	  if(!destroyed_by_clicking_stop) NotificationManager.putDroppedNotification(this.getApplicationContext());
    	  this.instancia = null;
          super.onDestroy();
    }
    
    @Override
    public int onStartCommand (Intent intent, int flags, int startId){
    	/* Start media player */
    	if(!thread_iniciado && this.waiting_for_answer==false){
    		this.iniciar_thread();
    	}
    	else{
    		Log.d("player","Waiting for reply");
    	}
		return START_STICKY;
    }

	public void onClick(DialogInterface dialog, int which) {
		this.waiting_for_answer = false;
		PlayerService.dialog = DIALOG_NODIALOG;
		if(which==DialogInterface.BUTTON_POSITIVE){
			/* Checks if it can establish connection to the server */
			if(!thread_iniciado){
		        this.iniciar_thread();
			}
		}
		else{
			PlayerService.destroyed_by_clicking_stop = true;
			this.stopSelf();
		}
	}
	
	private void iniciar_thread(){
		/* Change button/text */
		PlayerService.player_status = RadioBattletoadsActivity.PLAYER_CHECKINGCONNECTION;
		PlayButton.updateButtonAndStatus();
		/* Start thread */
		Log.d("player","Player started");
		Thread x = new Thread(this);
		x.start();
		thread_iniciado = true;
	}

	
}